package top.api.exception;




import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import top.api.common.ResUlt;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.stream.Collectors;


/**
 * springMVC异常处理器
 */
@RestControllerAdvice
@Slf4j
public class ProjectExceptionAdvice {

    /**
     * 未知异常
     * @param ex
     * @return
     */
   @ExceptionHandler(Exception.class)
    public ResUlt<Object> doException(Exception ex){
        log.error(ex.getMessage());
        return ResUlt.error("服务繁忙");
    }

    /**
     * 业务异常
     * @param ex
     * @return
     */
    @ExceptionHandler(ControllerException.class)
    public ResUlt<Object> doControllerException(ControllerException ex) {
        log.error(ex.getMessage());
        return ResUlt.error(ex.getMessage());
    }

    /**
     * 权限码异常
     */
    @ExceptionHandler(NotPermissionException.class)
    public ResUlt<Object> handleNotPermissionException(NotPermissionException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',权限码校验失败'{}'", requestURI, e.getMessage());
        return ResUlt.error("没有访问权限，请联系管理员授权");
    }

    /**
     * 角色权限异常
     */
    @ExceptionHandler(NotRoleException.class)
    public ResUlt<Object> handleNotRoleException(NotRoleException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',角色权限校验失败'{}'", requestURI, e.getMessage());
        return ResUlt.error("没有访问权限，请联系管理员授权");
    }

    /**
     * 认证失败
     */
    @ExceptionHandler(NotLoginException.class)
    public ResUlt<Object> handleNotLoginException(NotLoginException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',认证失败'{}',无法访问系统资源", requestURI, e.getMessage());
        return ResUlt.error("认证失败，无法访问系统资源");
    }


    /**
     * Validated异常拦截器
     *@Author yql
     *@Data 2023-03-04 11:21
     *@Description
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ResUlt<Object> handleValidException(MethodArgumentNotValidException e) {
        List<String> msgList = e.getBindingResult().getAllErrors()
                .stream()
                .map(ObjectError::getDefaultMessage)
                .collect(Collectors.toList());
        String msg = msgList.toString();
        msg = msg.substring(msg.lastIndexOf("[")+1,msg.lastIndexOf("]"));
        return ResUlt.error(msg);
    }
    /**
     * Validated异常拦截器
     *@Author yql
     *@Data 2023-03-04 11:21
     *@Description
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public ResUlt<Object> handleConstraintViolationException(ConstraintViolationException e) {
        List<String> msgList = e.getConstraintViolations()
                .stream()
                .map(ConstraintViolation::getMessage)
                .collect(Collectors.toList());
        String msg = msgList.toString();
        msg = msg.substring(msg.lastIndexOf("[")+1,msg.lastIndexOf("]"));
        return ResUlt.error(msg);
    }

    /**
     * Validated异常拦截器
     *@Author yql
     *@Data 2023-03-04 11:21
     *@Description
     */
    @ExceptionHandler(value = BindException.class)
    public ResUlt<Object> doBindException(BindException e) {
        List<ObjectError> allErrors = e.getAllErrors();

        List<String> errMsg = allErrors.stream()
                .map(DefaultMessageSourceResolvable::getDefaultMessage)
                .collect(Collectors.toList());
        String msg = errMsg.toString();
        msg = msg.substring(msg.lastIndexOf("[")+1,msg.lastIndexOf("]"));
        return ResUlt.error(msg);
    }

}
